home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 January: Mac OS SDK / Dev.CD Jan 96 SDK / Dev.CD Jan 96 SDK1.toast / Development Kits (Disc 1) / AppleScript / Development Tools / Sample Code / MenuScripter / Sources / MSFile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-25  |  15.3 KB  |  665 lines  |  [TEXT/MPS ]

  1. /*
  2.     MSFile.c
  3.     
  4.     Version 1.0d6
  5.     
  6.     Copyright © SRL Data 1992, 1993
  7.     
  8.     All rights reserved.
  9.     
  10.     Produced by : SRL Data
  11.     Originally Developed for UK.DTS
  12. */
  13. /*
  14.     Changes for 1.0d3:
  15.     27-Aug-92    : NH : Fix length of 'STR ' #-16396
  16. */
  17.     
  18. #include <Errors.h>
  19. #include <Resources.h>
  20. #include <Desk.h>
  21. #include <PLStringFuncs.h>
  22. #include <AppleEvents.h>
  23. #include <AERegistry.h>
  24. #include "MSFile.h"
  25.  
  26. /**-----------------------------------------------------------------------
  27.         Name:             FileError
  28.         Purpose:        Puts up an error alert.
  29.     -----------------------------------------------------------------------**/
  30.  
  31.     
  32. #pragma segment File
  33.  
  34. pascal void FileError(Str255 s, Str255 f)
  35.   {
  36.     short    alertResult;
  37.  
  38.     SetCursor(&qd.arrow);
  39.         ParamText(s, f, (unsigned char *)"", (unsigned char *)"");
  40.     alertResult = Alert(ErrorAlert, nil);
  41.     }
  42.  
  43. /**-----------------------------------------------------------------------
  44.         Name:             DoClose
  45.         Purpose:        Closes a window.
  46.     -----------------------------------------------------------------------**/
  47.  
  48. #pragma segment File
  49.  
  50. pascal OSErr DoClose(WindowPtr aWindow,Boolean canInteract,DescType dialogAnswer)
  51.   {
  52.     DPtr    aDocument;
  53.     short   alertResult;
  54.     Str255  theName;
  55.         OSErr   myErr;
  56.                         
  57.         myErr = noErr;
  58.         
  59.     if (gWCount>0)
  60.       {
  61.         aDocument = DPtrFromWindowPtr(aWindow);
  62.             
  63.                 if (aDocument->dirty)
  64.                     if (canInteract && (dialogAnswer==kAEAsk))
  65.                         {
  66.                             if (aDocument->everSaved == false)
  67.                                 GetWTitle(aWindow, theName); /* Pick it up as a script may have changed it */
  68.                             else
  69.                                 PLstrcpy(theName, aDocument->theFileName);
  70.                                 
  71.                             ParamText((unsigned char *)"\pSave Changes for ", theName, (unsigned char *)"", (unsigned char *)"");
  72.                           SetCursor(&qd.arrow);
  73.                             alertResult = Alert(AdviseAlert, nil);
  74.                             switch (alertResult) {
  75.                               case aaSave    :if (aDocument->everSaved == false)
  76.                                                                     {
  77.                                                                         myErr = GetFileNameToSaveAs(aDocument);
  78.                                                                         if (myErr == noErr)
  79.                                                                             myErr = DoSave(aDocument, aDocument->theFSSpec);
  80.                                                                             
  81.                                                                         if (myErr==noErr)
  82.                                                                             AssocAllSections(aDocument);
  83.                                                                     }
  84.                                                                 else
  85.                                                                     myErr = SaveUsingTemp(aDocument);
  86.                                                                 break;
  87.                                                                 
  88.                                 case aaCancel : return(userCanceledErr);
  89.                                                 break;
  90.                                                                 
  91.                                 case aaDiscard: aDocument->dirty = false;
  92.                             }
  93.                         }
  94.                     else
  95.                         {
  96.                             if (dialogAnswer==kAEYes)
  97.                                 if (aDocument->everSaved == false)
  98.                                     {
  99.                                         if (canInteract)
  100.                                             {
  101.                                               myErr = GetFileNameToSaveAs(aDocument);
  102.                                                 if (myErr==noErr)
  103.                                                     myErr = DoSave(aDocument, aDocument->theFSSpec);
  104.                                                 if (myErr==noErr)
  105.                                                     AssocAllSections(aDocument);
  106.                                             }
  107.                                         else    
  108.                                             return(errAENoUserInteraction);
  109.                                     }
  110.                                 else
  111.                                     myErr = SaveUsingTemp(aDocument);
  112.                             else
  113.                                 myErr = noErr; /* Don't save */
  114.                         }
  115.                 
  116.                 if (myErr==noErr)
  117.                     {
  118.                         if (aDocument->numSections)
  119.                             DeRegisterAllSections(aDocument);
  120.                         CloseMyWindow(aWindow);
  121.                     }
  122.             }
  123.         else
  124.           myErr = errAEIllegalIndex;
  125.             
  126.         return(myErr);
  127.     }
  128.  
  129. #pragma segment File
  130.  
  131. //  DoQuit
  132. //  saveOpt - one of kAEAsk,kAEYes,kAENo
  133. //  if kAEYes or kAEAsk then AEInteactWithUser should have been called
  134. //  before DoQuit. Assumes that it can interact if it needs to.
  135.  
  136. pascal void DoQuit(DescType saveOpt)
  137.   {
  138.     WindowPtr    aWindow;
  139.     WindowPtr    nextWindow;
  140.     WindowPeek   nextWPeek;
  141.     short        theKind;
  142.     OSErr        check;
  143.  
  144.     aWindow = FrontWindow();
  145.      
  146.         while (aWindow)
  147.             {
  148.                 nextWPeek  = ((WindowPeek)aWindow)->nextWindow;
  149.                 nextWindow = &nextWPeek->port;
  150.                 if (Ours(aWindow))
  151.                     {
  152.                         check = DoClose(aWindow, true, saveOpt);
  153.                         if (check!=noErr)
  154.                             return;
  155.                     }
  156.                 else
  157.                     {
  158.                         theKind = ((WindowPeek)aWindow)->windowKind;
  159.                         if (theKind < 0)
  160.                             CloseDeskAcc(theKind);
  161.                     }
  162.                 aWindow = nextWindow;
  163.             }     /*WHILE loop*/
  164.         gQuitting = true;
  165.     }
  166.  
  167. pascal OSErr GetFile(FSSpec *theFSSpec)
  168.   {
  169.     SFTypeList         myTypes;
  170.     StandardFileReply  reply;
  171.  
  172.         myTypes[0] = 'TEXT';
  173.  
  174.         StandardGetFile(nil, 1, myTypes, &reply);
  175.  
  176.         if (reply.sfGood)
  177.             {
  178.                 *theFSSpec = reply.sfFile;
  179.                 return(noErr);
  180.             }
  181.         else
  182.             return(userCanceledErr);
  183.  }
  184.  
  185. #pragma segment File
  186.  
  187.  
  188. pascal OSErr DoCreate(FSSpec theSpec)
  189.   {
  190.       OSErr err;
  191.  
  192.       err = FSpCreate(&theSpec, MenuScripterAppSig, 'TEXT', smSystemScript);
  193.  
  194.       if (err != noErr)
  195.               ShowError((unsigned char *)"\pDoCreate", err);
  196.                 
  197.             return(err);
  198.     }
  199.  
  200. #pragma segment File
  201.  
  202.  
  203. pascal OSErr WriteFile(DPtr      theDocument,
  204.                                              short     refNum,
  205.                        FSSpec    theFSSpec)
  206.   {
  207.     short        resFile;
  208.     long         length;
  209.     HHandle      theHHandle;
  210.     StScrpHandle theSHandle;
  211.     OSErr        err;
  212.     StringHandle theAppName;
  213.         short        oldSelStart;
  214.         short        oldSelEnd;
  215.         Handle       thePHandle;
  216.         Handle       myText;
  217.                 
  218. /*        WriteFile := 1; */
  219.  
  220.     /*first write out the text to the data fork*/
  221.         
  222.         length = (*(theDocument->theText))->teLength;
  223.         
  224.         myText = (*(theDocument->theText))->hText;
  225.         
  226.     HLock(myText);
  227.     
  228.         err = FSWrite(refNum, &length, *myText);
  229.         if (err)
  230.           return(err);
  231.             
  232.     HUnlock(myText);
  233.  
  234.         /*we are writing to a temporary file, so we need to create the resource file*/
  235.         /*before writing out the resources*/
  236.         /*now open the resource file*/
  237.         
  238.         HCreateResFile(theFSSpec.vRefNum, theFSSpec.parID, theFSSpec.name);
  239.         err = ResError();
  240.         if (err)
  241.           {
  242.                 ShowError((unsigned char *)"\pHCreateResFile", err);
  243.                 return(err);
  244.             }
  245.  
  246.     resFile = HOpenResFile(theFSSpec.vRefNum, theFSSpec.parID, theFSSpec.name, fsWrPerm);
  247.     err = ResError();
  248.  
  249.     if (err)
  250.           {
  251.                 ShowError((unsigned char *)"\pHOpenResFile", err);
  252.                 return(err);
  253.             }
  254.  
  255.      /*write out our 'TFSF' resource to file*/
  256.                 
  257.         oldSelStart = (*(theDocument->theText))->selStart;
  258.         oldSelEnd   = (*(theDocument->theText))->selEnd;
  259.         TESetSelect(0,32000, theDocument->theText);
  260.                 
  261.     theSHandle = GetStylScrap(theDocument->theText);
  262.                 
  263.         TESetSelect(oldSelStart,oldSelEnd, theDocument->theText);
  264.                 
  265.     AddResource((Handle)theSHandle, 'TFSF', 255, (unsigned char *)"\pStyle Info");
  266.     err = ResError();
  267.     if (err)
  268.           {
  269.                 ShowError((unsigned char *)"\pAddResource- TFSF", err);
  270.                 return(err);
  271.             }
  272.                     
  273.         /* write out the printer info */
  274.                 
  275.         if (theDocument->thePrintSetup)
  276.             {
  277.                 thePHandle = (Handle)theDocument->thePrintSetup;
  278.                 err = HandToHand(&thePHandle);
  279.                 
  280.                 AddResource(thePHandle, 'TFSP', 255, (unsigned char *)"\pPrinter Info");
  281.                 err = ResError();
  282.                 if (err)
  283.                     {
  284.                         ShowError((unsigned char *)"\pAddResource- TFSP", err);
  285.                         return(err);
  286.                     }
  287.             }
  288.                 
  289.                 
  290.         theHHandle = (HHandle)NewHandle(sizeof(HeaderRec));
  291.     HLock((Handle)theHHandle);
  292.  
  293.         GetFontName(theDocument->theFont, (unsigned char *)&(*theHHandle)->theFont);
  294.         (*theHHandle)->theSize     = theDocument->theSize;
  295.         (*theHHandle)->theStyle    = theDocument->theStyle;
  296.         (*theHHandle)->lastID      = theDocument->lastID;
  297.         (*theHHandle)->numSections = theDocument->numSections;
  298.  
  299.         HUnlock((Handle)theHHandle);
  300.  
  301.         AddResource((Handle)theHHandle, 'TFSS', 255, (unsigned char *)"\pHeader Info");
  302.  
  303.         err = ResError();
  304.         if (err)
  305.             {
  306.                 ShowError((unsigned char *)"\pAddResource- TFSS", err);
  307.                 return(err);
  308.             }
  309.  
  310.         /*if we have any sections, write out the records and resources*/
  311.         
  312.         if (theDocument->numSections)
  313.             {
  314.                 /*now write out the section records*/
  315.                 SaveSections(theDocument);
  316.                 
  317.                 /*write the latest versions of all editions to their containers*/
  318.  
  319.                 WriteAllEditions(theDocument);
  320.                 /*now close the resource file*/
  321.                 err = ResError();
  322.                 if (err)
  323.                     {
  324.                         ShowError((unsigned char *)"\pCloseResFile", err);
  325.                         return(err);
  326.                     }
  327.             }
  328.  
  329.         /*Now put an AppName in for Finder in 7.0*/
  330.  
  331.         theAppName = (StringHandle)NewHandle(20); // at least as long as (unsigned char *)"\pMenuScripter"
  332.         PLstrcpy(*theAppName,(unsigned char *)"\pMenuScripter");
  333.         
  334.         AddResource((Handle)theAppName, 'STR ', -16396, (unsigned char *)"\pFinder App Info");
  335.  
  336.         err = ResError();
  337.  
  338.         if (err)
  339.             {
  340.                 ShowError((unsigned char *)"\pAppName", err);
  341.                 return(err);
  342.             }
  343.  
  344.         CloseResFile(resFile);
  345.  
  346.         return(noErr);
  347.     } /* WriteFile */
  348.  
  349. #pragma segment File
  350.  
  351. pascal OSErr ReadFile(DPtr   theDocument,
  352.                                             short  refNum,
  353.                       Str255 fn)
  354.  {
  355.         long            theSize;
  356.         short           resFile;
  357.         OSErr           err;
  358.         HHandle         aHandle;
  359.         Handle          gHandle;
  360.  
  361.         err = GetEOF(refNum, &theSize);
  362.                 if (err)
  363.           return(err);
  364.  
  365.         /*we're only using TE, so check that there is not more than 32K worth of text*/
  366.                 
  367.         if (theSize > 32000)
  368.           return(1);
  369.  
  370.         gHandle = NewHandle(theSize);
  371.         HLock(gHandle);
  372.                 err = FSRead(refNum, &theSize, *gHandle);
  373.                 
  374.         if (err)
  375.           {
  376.             HUnlock(gHandle);
  377.                         return(err);
  378.           }
  379.                                 
  380.                 resFile = HOpenResFile(theDocument->theFSSpec.vRefNum, 
  381.                                                              theDocument->theFSSpec.parID,
  382.                                                              fn,
  383.                                                              fsWrPerm);
  384.                 if (resFile == -1)
  385.                     err = fnfErr;
  386.                     
  387.                 theDocument->numSections = 0;
  388.                 
  389.                 if (err==noErr)
  390.                     {
  391.                         aHandle = nil;
  392.         
  393.                         if (Count1Resources('TFSS'))
  394.                             aHandle = (HHandle)Get1Resource('TFSS', 255);
  395.         
  396.                         if (aHandle)
  397.                             theDocument->numSections = (*aHandle)->numSections;
  398.                             
  399.                         /*
  400.                             New Format Info
  401.                         */
  402.                         
  403.                         aHandle = nil;
  404.                         
  405.                         if (Count1Resources('TFSF'))
  406.                             aHandle = (HHandle)Get1Resource('TFSF', 255);
  407.                             
  408.                         HLock(gHandle);
  409.                         TEStylInsert(    *gHandle,
  410.                                                     GetHandleSize(gHandle),
  411.                                                     (StScrpHandle)aHandle,
  412.                                                     theDocument->theText);
  413.                                         
  414.                         HUnlock(gHandle);
  415.                         
  416.                         /*
  417.                             If there is a print record saved, ditch the old one
  418.                             created by new document and fill this one in
  419.                         */
  420.                         if (Count1Resources('TFSP'))
  421.                             {
  422.                                 if (theDocument->thePrintSetup)
  423.                                     DisposHandle((Handle)theDocument->thePrintSetup);
  424.                                 
  425.                                 theDocument->thePrintSetup = (THPrint)Get1Resource('TFSP', 255);
  426.                               err = HandToHand((Handle *)&theDocument->thePrintSetup);
  427.                                 
  428.                                 PrValidate(theDocument->thePrintSetup);
  429.                             }
  430.                                                     
  431.                         if (theDocument->numSections)
  432.                             {
  433.                                 ReadSectionRecords(theDocument);
  434.                                 ReadAllSectionResources(theDocument);
  435.                             }
  436.         
  437.                         CloseResFile(resFile);
  438.         
  439.                         err = ResError();
  440.                         if (err)
  441.                             {
  442.                                 ShowError((unsigned char *)"\pread file- CloseResFile", err);
  443.                                 return(err);
  444.                             }
  445.           }
  446.                 else
  447.                     TESetText(*gHandle, 
  448.                               GetHandleSize(gHandle), 
  449.                                         theDocument->theText);
  450.                     
  451.                 if (gHandle)
  452.                     DisposHandle(gHandle);
  453.                     
  454.                 if (err==fnfErr)
  455.                     err = noErr;
  456.  
  457.         return(err);
  458.         } /* ReadFile */
  459.  
  460. /** -----------------------------------------------------------------------
  461.         Name:             GetFileContents
  462.         Purpose:        Opens the document specified by theFSSpec and puts
  463.                                 the contents into theDocument.
  464.      -----------------------------------------------------------------------**/
  465.  
  466.     
  467. #pragma segment File
  468.  
  469. pascal OSErr GetFileContents(FSSpec theFSSpec, DPtr theDocument)
  470.   {
  471.      OSErr            err;
  472.      short            theRefNum;
  473.  
  474.             /*this can be called from two places- on an OpenDoc AppleEvent*/
  475.             /*and by the user just selecting Open from the File Menu*/
  476.             /*assume that the CFS is correct when the routine is called*/
  477.  
  478.             err = FSpOpenDF(&theFSSpec,
  479.                                           fsRdWrPerm,
  480.                                           &theRefNum);
  481.             if (err)
  482.                 {
  483.                     ShowError((unsigned char *)"\pFSpOpenDF", err);
  484.                     return(err);
  485.                 }
  486.             else
  487.                 {
  488.                     err = ReadFile(theDocument, theRefNum, theFSSpec.name);
  489.                     if (err)
  490.                         {
  491.                             ShowError((unsigned char *)"\pReadFile", err);
  492.                             return(err);
  493.                         }
  494.                     err=FSClose(theRefNum);
  495.                     if (err)
  496.                         {
  497.                             ShowError((unsigned char *)"\pFSClose", err);
  498.                             return(err);
  499.                         }
  500.                     return(noErr);
  501.                 }
  502.         }
  503.  
  504.     
  505. #pragma segment File
  506.  
  507. pascal OSErr SaveUsingTemp(DPtr theDocument)
  508.   {
  509.     Str255           tempName;
  510.     OSErr            err;
  511.         FSSpec                tempFSSpec;
  512.  
  513.         /*save the file to disk using a temporary file*/
  514.         /*this is the recommended way of doing things*/
  515.         /*first write out the file to disk using a temporary filename*/
  516.         /*if it is sucessfully written, exchange the temporary file with the last one saved*/
  517.     /*then delete the temporary file- so if anything goes wrong, the original version is still there*/
  518.         /*first generate the temporary filename*/
  519.  
  520.         GetTempFileName(theDocument, (unsigned char *)&tempName);
  521.         /*create this file on disk*/
  522.  
  523.         tempFSSpec      = theDocument->theFSSpec;
  524.         PLstrcpy(tempFSSpec.name,tempName);
  525.             
  526.         err = DoCreate(tempFSSpec);    
  527.  
  528.         /*now save the file as normal*/
  529.         
  530.         if (err==noErr)
  531.             err = DoSave(theDocument, tempFSSpec);
  532.         
  533.         if (err == noErr)
  534.             err = FSpExchangeFiles(&tempFSSpec, &theDocument->theFSSpec);
  535.  
  536.         /*we've exchanged the files, now delete the temporary one*/
  537.         
  538.         if (err==noErr)
  539.           err = FSpDelete(&tempFSSpec);
  540.  
  541.         return(err);
  542.     }
  543.  
  544.     
  545. #pragma segment File
  546.  
  547. /*
  548.     Fills in the document record with the user chosen destination
  549. */
  550.  
  551. pascal OSErr GetFileNameToSaveAs(DPtr theDocument)
  552.     {            
  553.     StandardFileReply   reply;
  554.     OSErr               err;
  555.         Str255              suggestName;
  556.  
  557.         GetWTitle(theDocument->theWindow, suggestName);
  558.  
  559.         StandardPutFile((unsigned char *)"\pSave Document As:", suggestName, &reply);
  560.  
  561.     if (reply.sfGood)
  562.             {                
  563.                 err = FSpDelete(&reply.sfFile);
  564.                 
  565.                 if (!((err==noErr) || (err==fnfErr)))
  566.                     return(err);
  567.                 else
  568.                     err = noErr;
  569.                     
  570.                 theDocument->theFSSpec = reply.sfFile;
  571.                 PLstrcpy(theDocument->theFileName, reply.sfFile.name);
  572.             }
  573.         else
  574.             err = userCanceledErr;
  575.         
  576.         return(err);
  577.  } /* GetFileNameToSaveAs */
  578.  
  579.     
  580. #pragma segment File
  581.  
  582. pascal OSErr DoSave(DPtr   theDocument, FSSpec theFSSpec)
  583.   {
  584.     short      refNum;
  585.     OSErr      fileErr;
  586.  
  587.         fileErr = FSpOpenDF(&theFSSpec, fsRdWrPerm, &refNum);
  588.         
  589.         if (fileErr == fnfErr)
  590.             {
  591.               fileErr = DoCreate(theFSSpec);
  592.                 
  593.                 if (fileErr)
  594.                     return(fileErr);
  595.                     
  596.                 fileErr = FSpOpenDF(&theFSSpec, fsRdWrPerm, &refNum);
  597.             }
  598.  
  599.         if (fileErr == noErr)
  600.             {
  601.               fileErr = WriteFile(theDocument, refNum, theFSSpec);
  602.                 
  603.                 if (fileErr==noErr)
  604.                     theDocument->dirty = false;
  605.                     
  606.                 fileErr = FSClose(refNum);
  607.             }
  608.         else
  609.             FileError((unsigned char *)"\perror opening file ", theFSSpec.name);
  610.         
  611.         return(fileErr);
  612.     }
  613.  
  614.     
  615. #pragma segment File
  616.  
  617. pascal OSErr OpenOld(FSSpec aFSSpec)
  618.     {        
  619.       DPtr  theDocument;
  620.         OSErr fileErr;
  621.  
  622.         theDocument = NewDocument(true);
  623.         
  624.         SetWTitle(theDocument->theWindow, aFSSpec.name);
  625.         
  626.         SetPort(theDocument->theWindow);
  627.         
  628.         theDocument->theFSSpec   = aFSSpec;
  629.         
  630.         PLstrcpy(theDocument->theFileName,aFSSpec.name);
  631.         
  632.         theDocument->dirty       = false;
  633.         theDocument->everSaved   = true;
  634.  
  635.     fileErr = GetFileContents(aFSSpec, theDocument);
  636.         
  637.         if (fileErr == noErr)
  638.             {
  639.                 ResizeWindow(theDocument);
  640.                 ShowWindow(theDocument->theWindow);
  641.             }
  642.         else
  643.             FileError((unsigned char *)"\pError Opening ", aFSSpec.name);
  644.                     
  645.         return(fileErr);
  646.     } /* OpenOld */
  647.  
  648.     
  649. #pragma segment File
  650.  
  651. pascal OSErr OpenUsingAlias(AliasHandle theAliasH)
  652.   {
  653.     OSErr    err;
  654.     FSSpec   aFSSpec;
  655.     Boolean  dummy;
  656.  
  657.         err = ResolveAlias(nil, theAliasH, &aFSSpec, &dummy);
  658.         
  659.         if (err == noErr)
  660.             err = OpenOld(aFSSpec);
  661.                     
  662.         return(err);
  663.     }
  664.  
  665.